事务有哪些特性
- 原子性:一个事物中的所有操作,要么全部完成,要么全部不完成
- 一致性:事物操作前后,数据满足完整性约束,比如A用户给B用户转钱,A用户的账号会减去X元,B用的账号会多X元
- 隔离性:数据库允许多个事物并行对数据进行读写操作
- 持久性:事务结束后,对于数据的修改时永久的
- 原子性:由undo log实现
- 持久性:由redo log来保证
- 隔离性:由MVCC实现
- 一致性:由原子性、隔离性、持久性一起来保证
并发执行时会有哪些问题
在多个事物同时处理时,不同的隔离级别下,可能会出现
- 脏读(读还没有提交事务的数据)
- 不可重复读(读取的数据前后两次数据不一致)
- 幻读的问题(数据的行数前后不一致)
不同的隔离级别
- 读未提交:一个事物还没有提交,但可以看到这个事物的结果
- 读已提交:一个事物提交后,才能看到事物的结果
- 可重复读:一个事物在执行过程中,看到的数据和事物启动前保持一致
- 串行化:对记录加上读写锁,在多个事物对这个记录进行读写操作时,如果有读写冲突,那么后执行的必须等待先执行的,执行完成才能继续执行
MVCC的原理
read view的机制

- creator_trx_id:表示创建该Read View的事物id
- m_ids :表示创建该Read View时,当前数据库的「活跃且未提交」的事物id列表
- min_trx_id:表示当前数据库中「活跃事物」中id最小的事物id
- max_trx_id表示创建Read View时,当前数据库中应该给的下一个事物id
通过版本链的方式,来控制并发事物访问对于同一个记录的行为
可重复读下的幻读问题
InnoDB 默认隔离级别是可重复读。当前读(SELECT … FOR UPDATE / UPDATE / DELETE)会加 Next-Key Lock:记录锁加上间隙锁,挡住「插入一条会让本次范围查询多出一行」的并发。
快照读(普通 SELECT)走 Read View,看不到事务开始后才提交的插入,所以快照读看不到幻行。幻读出现在:同一事务里先快照读、再当前读,或两次当前读中间有别的事务插入并提交。
要复现,用当前读对着一个范围:事务 A SELECT * FROM t WHERE id > 10 FOR UPDATE,事务 B 插入 id=15 并提交。没有间隙锁时 A 再当前读会多出一行;有 Next-Key 时 B 会堵住。